use std::collections::HashMap;

use serde::{Deserialize, Serialize};

use argon2::{self, Config};
use rand::{thread_rng, Rng};
use rusqlite::Error;

use crate::db::create_user_in_db;

#[derive(Serialize, Deserialize, Debug, PartialEq, Builder)]
#[builder(name = "BSUserConstructor")]
pub struct BSUser {
    #[builder(setter(into))]
    pub username: String,
    #[builder(setter(into))]
    pub password: String,
    pub offset: Option<u32>,
}

#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct BSUsers {
    pub items: HashMap<String, BSUser>,
}

impl BSUser {
    pub fn check_pwd(&self, password: &str) -> bool {
        argon2::verify_encoded(&self.password, password.as_bytes()).unwrap()
    }

    pub fn create(username: &str, password: &str) -> Result<BSUser, Error> {
        let mut b = BSUserConstructor::default()
            .username(username)
            .password(password)
            .build()
            .unwrap();
        b.set_password(&password).unwrap();
        create_user_in_db(b)
    }
    pub fn set_password(&mut self, password: &str) -> Result<(), argon2::Error> {
        let mut salt = [0u8; 32];
        thread_rng().fill(&mut salt[..]);
        let config = Config::default();
        let m = argon2::hash_encoded(password.as_bytes(), &salt, &config)?;
        self.password = m;
        Ok(())
    }
}
